package org.qq120011676.fileserver.fileserver.controller;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.constraints.NotEmpty;
import lombok.RequiredArgsConstructor;
import org.qq120011676.fileserver.fileserver.controller.resp.FileUploadResp;
import org.qq120011676.fileserver.fileserver.service.FileService;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.core.io.Resource;
import org.springframework.http.*;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.List;
import java.util.Objects;
import java.util.Optional;

@RequiredArgsConstructor
@RestController
@RequestMapping("file")
public class FileController {
    private final FileService fileService;

    @PostMapping("upload")
    public List<FileUploadResp> upload(@Validated @NotEmpty List<MultipartFile> files) {
        return fileService.upload(files);
    }

    @PostMapping("uploadBytes")
    public String uploadBytes(@RequestBody @Validated @NotEmpty byte[] bytes) {
        return fileService.uploadBytes(bytes);
    }

    @RequestMapping("query")
    public List<String> query(@RequestParam @Validated @NotEmpty List<String> signs) {
        return fileService.query(signs);
    }

    @RequestMapping(value = "download", method = {RequestMethod.GET, RequestMethod.POST})
    public ResponseEntity<Resource> download(@RequestParam @Validated @NotEmpty List<String> signs,
                                             String filename,
                                             HttpServletRequest request) {
        if (Objects.equals(request.getMethod(), HttpMethod.GET.name())) {
            filename = new String(Base64.getUrlDecoder()
                    .decode(filename), StandardCharsets.UTF_8);
        }
        byte[] bytes = fileService.get(signs);
        return createResponseEntity(bytes, null, filename);
    }

    @RequestMapping(value = "preview", method = {RequestMethod.GET, RequestMethod.POST})
    public ResponseEntity<Resource> preview(@RequestParam @Validated @NotEmpty List<String> signs,
                                            String contentType,
                                            HttpServletRequest request) {
        if (Objects.equals(request.getMethod(), HttpMethod.GET.name())) {
            contentType = new String(Base64.getUrlDecoder()
                    .decode(contentType), StandardCharsets.UTF_8);
        }
        byte[] bytes = fileService.get(signs);
        return createResponseEntity(bytes, contentType, null);
    }

    private ResponseEntity<Resource> createResponseEntity(byte[] bytes, String contentType, String filename) {
        ResponseEntity.BodyBuilder bodyBuilder = ResponseEntity.ok()
                .contentType(Optional.ofNullable(contentType)
                        .map(MediaType::parseMediaType)
                        .orElse(MediaType.APPLICATION_OCTET_STREAM));
        if (StringUtils.hasText(filename)) {
            bodyBuilder = bodyBuilder.header(HttpHeaders.CONTENT_DISPOSITION,
                    ContentDisposition.attachment()
                            .filename(filename, StandardCharsets.UTF_8)
                            .build().toString());
        }
        Resource resource = new ByteArrayResource(bytes);
        return bodyBuilder.body(resource);
    }
}
